package initSystem

import (
	"context"
	"github.com/redis/go-redis/v9"
	"github.com/spf13/viper"
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
	"gorm.io/gorm/logger"
	"log"
	"os"
	"time"
)

var (
	DB        *gorm.DB
	AppConfig *viper.Viper
	Logger    *zap.Logger
	RDB       *redis.Client
)

func InitDB() error {
	dsn := AppConfig.GetString("db.dsn")
	db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
		Logger: logger.New(
			log.New(os.Stdout, "\r\n", log.LstdFlags), // 标准输出
			logger.Config{
				SlowThreshold:             time.Second, // 慢 SQL 阈值
				LogLevel:                  logger.Info, // 日志级别
				IgnoreRecordNotFoundError: true,        // 忽略未找到错误
				Colorful:                  true,        // 彩色输出
			},
		),
	})
	if err != nil {
		panic("连接数据库失败: " + err.Error())
	}
	sqlDB, err := db.DB()
	if err != nil {
		panic("获取数据库实例失败: " + err.Error())
	}
	// 设置连接池
	sqlDB.SetMaxIdleConns(10)           // 空闲连接池中的最大连接数
	sqlDB.SetMaxOpenConns(100)          // 数据库的最大打开连接数
	sqlDB.SetConnMaxLifetime(time.Hour) // 连接可复用的最大时间
	DB = db
	return db.Error
}

func InitConfig(configName string) error {
	viper.SetConfigName(configName)
	viper.AddConfigPath("./configs")
	viper.SetConfigType("yaml")
	viper.AutomaticEnv()

	AppConfig = viper.GetViper()
	return viper.ReadInConfig()
}

func InitCustomLogger() error {
	config := zap.Config{
		Level:       zap.NewAtomicLevelAt(zap.InfoLevel), // 日志级别
		Development: false,                               // 开发模式
		Encoding:    "console",                           // 输出格式：json 或 console
		EncoderConfig: zapcore.EncoderConfig{ // 编码器配置
			TimeKey:        "ts",
			LevelKey:       "level",
			NameKey:        "logger",
			CallerKey:      "caller",
			MessageKey:     "msg",
			StacktraceKey:  "stacktrace",
			LineEnding:     zapcore.DefaultLineEnding,
			EncodeLevel:    zapcore.LowercaseLevelEncoder,
			EncodeTime:     zapcore.EpochTimeEncoder,
			EncodeDuration: zapcore.SecondsDurationEncoder,
			EncodeCaller:   zapcore.ShortCallerEncoder,
		},
		OutputPaths:      []string{"stdout"}, // 输出到控制台
		ErrorOutputPaths: []string{"stderr"}, // 错误输出
	}
	build, err := config.Build()
	Logger = build
	return err
}

var ctx = context.Background()

func InitRDB() {
	// 创建 Redis 客户端
	rdb := redis.NewClient(&redis.Options{
		Addr:     AppConfig.GetString("redis.host"),     // Redis 服务器地址
		Password: AppConfig.GetString("redis.password"), // 密码
		DB:       0,                                     // 使用默认 DB
	})

	// 测试连接
	_, err := rdb.Ping(ctx).Result()
	if err != nil {
		panic(err)
	}
	RDB = rdb
}
